/***************
 * core.js     *
 *             *
 * Objeto Core *
 ***************/

var Core = {
    /**
     * @var object
     */
    "keyCode": {
        "DOT": 46,
        "BACKSPACE": 8,
        "CAPS_LOCK": 20,
        "COMMA": 188,
        "CONTROL": 17,
        "DELETE": 46,
        "DOWN": 40,
        "END": 35,
        "ENTER": 13,
        "ESCAPE": 27,
        "F1": 112,
        "F2": 113,
        "F3": 114,
        "F4": 115,
        "F5": 116,
        "F6": 117,
        "F7": 118,
        "F8": 119,
        "F9": 120,
        "F10": 121,
        "F11": 122,
        "F12": 123,
        "HOME": 36,
        "INSERT": 45,
        "LEFT": 37,
        "PAGE_DOWN": 34,
        "PAGE_UP": 33,
        "PERIOD": 190,
        "RIGHT": 39,
        "SHIFT": 16,
        "SPACE": 32,
        "TAB": 9,
        "UP": 38
    },
    /**
     * @var object
     */
    "keyCodeNumPad": {
        "NUMPAD_ADD": 107,
        "NUMPAD_DECIMAL": 110,
        "NUMPAD_DIVIDE": 111,
        "NUMPAD_ENTER": 108,
        "NUMPAD_MULTIPLY": 106,
        "NUMPAD_SUBTRACT": 109
    },
    /**
     * Verifica se o keyCode disparado quando uma tecla é pressionada está no
     * array fornecido
     *
     * @param arrCode array|json|number|string
     * @param e event
     * @return boolean
     */
    "keyCodeListener": function (arrCode, e)
    {
        Core.console.group('keyCodeListener', true);
        e = e || window.event;
        var keyCode = e.keyCode;
        Core.console.debug('keyCode: ' + keyCode);
        Core.console.debug(arrCode);
        if (typeof arrCode === 'string' || typeof arrCode === 'number') {
            if (keyCode === arrCode) {
                Core.console.debug('keyCode encontrado', 'true:', Core.console.type.INFO);
                Core.console.groupEnd();
                return true;
            }
        } else {
            for (var x in arrCode) {
                if (arrCode[x] === keyCode) {
                    Core.console.debug('keyCode encontrado', 'true:', Core.console.type.INFO);
                    Core.console.groupEnd();
                    return true;
                }
            }
        }
        Core.console.debug('keyCode não encontrado', 'false:', Core.console.type.WARN);
        Core.console.groupEnd();
        return false;
    },
    /**
     * Verifica se o char disparado quando uma tecla é pressionada está no
     * array fornecido
     *
     * @param str string
     * @param e event
     * @return boolean
     */
    "charListener": function (str, e)
    {
        Core.console.group('charsListener', true);
        e = e || window.event;
        var charCode = e.charCode;
        var key = String.fromCharCode(charCode);
        Core.console.debug('charCode: ' + charCode, 'char :' + key, 'allowedChars :' + str);
        if (str.indexOf(key) >= 0) {
            Core.console.debug('char encontrado', 'true:', Core.console.type.INFO);
            Core.console.groupEnd();
            return true;
        }

        Core.console.debug('char não encontrado', 'false:', Core.console.type.WARN);
        Core.console.groupEnd();
        return false;
    },
    "goToBackPage": function (comeFrom)
    {
        comeFrom = comeFrom || '';
        if (history.length <= 1) {
            alert('Não pode mais voltar');
            $(comeFrom).remove();
        } else {
            Core.console.debug('Volta...');
            history.back();
        }
    },
    "close": function (comeFrom)
    {
        comeFrom = comeFrom || '';
        if (is_null(window.opener)) {
            alert('Esta página não pode ser fechada');
            $(comeFrom).remove();
        } else {
            Core.console.debug('Tiau...');
            window.close();
        }
    },
    "mountUrl": function (options)
    {
        var module = isset(options.module) ? options.module : baseRequest.module;
        var request = new Array();
        //É upload de arquivo?
        if (options.fileUpload) {
            request.push('/public');
        } else if (options.ssl) {
            request.push('/private');
        } else {
            request.push(baseUrl);
        }

        if (isset(options.route)) {
            request.push(options.route);
        } else {

            request.push(isset(options.module) ? options.module : baseRequest.module);
            request.push(isset(options.controller) ? options.controller : baseRequest.controller);
            request.push(isset(options.action) ? options.action : baseRequest.action);
        }
        return request.join("/");
    },
    "refresh": function (url)
    {
        
        if (typeof url !== 'undefined') {
            var request = baseUrl + "/";
            if (baseRequest.module !== 'default') {
                request += baseRequest.module + "/";
            }
            request += baseRequest.controller + "/";
            request += baseRequest.action;
            url = url || request;
            return window.location.href = url;
        } else {
            return location.reload();
        }

    },
    /**
     * Executa um redirect com parametros por GET ou por POST
     *
     * @example
     *   Core.redirect({
     *       "module" : "nome-do-modulo"
     *       "controller" : "nome-do-controlador"
     *       "action" : "nome-da-acao"
     *       "type" : "post"
     *       "data" : {}
     *   });
     * @param options JSON
     * @return void
     */
    "redirect": function (options)
    {
        try {
            if (typeof (options) !== "object") {
                throw new Core.Exception("Core.redirect(): Passe as opções corretamente");
            }

            var type = isset(options.type) ? options.type : "get";
            var data = isset(options.data) ? options.data : {};
            var url = Core.mountUrl(options);
            if (!in_array(type, ["post", "get"])) {
                throw new Core.Exception("Core.redirect(): O tipo só pode ser 'get' ou 'post'");
            }

            if (type === 'get') {
                var parameters = '';
                if (typeof (data) === 'object') {
                    if (isset(data.jquery)) {
                        parameters = '?' + data.serialize();
                    } else {
                        for (var i in data) {
                            if (isset(data.i)) {
                                parameters += '/' + i + '/' + data.i;
                            } else {
                                parameters += '/' + i + '/' + data[i];
                            }
                        }
                    }
                } else if (typeof (data) === "string") {
                    data = (data !== '') ? '/' + data : '';
                    parameters = data;
                } else {
                    throw new Core.Exception("Core.redirect(): Tipo dos dados inválido. Só pode object ou string");
                }

                Core.refresh(url + parameters);
            } else { // type === post
                var formRedirect = Core.form.mountHiddenForm('formRedirect', url, data);
                formRedirect.submit();
            }
        } catch (e) {
            Core.exceptionHandler(e);
        }
    },
    /**
     * Exception
     * @param message string
     * @param code int
     * @var object Core.Exception
     */
    "Exception": function (message, code)
    {
        this.message = message || "Exceção sem mensagem!";
        this.code = code || 0;
        Core.Exception.prototype.toString = function ()
        {
            return "Core.Exception: [" + this.code + "] '" + this.message + "'";
        };
    },
    /**
     * @param e mixed
     * @return void
     */
    "exceptionHandler": function (e)
    {
        var c = Core.console;
        if (e instanceof Core.Exception) {
            c.group("Core.Exception: " + e.message, true);
            c.debug(e, '', Core.console.type.ERROR);
            c.groupEnd();
        } else {
            c.debug(e, '', Core.console.type.ERROR);
        }
    },
    /**
     * @param callback function
     * @param param mixed
     * @return mixed
     */
    "callbackHandler": function (callback, param)
    {
        if ($.isFunction(callback)) {
            return callback(param);
        }
        return false;
    },
    /**
     * @param value mixed
     * @return boolean
     */
    "isArray": function (value)
    {
        value = value || null;
        if (value !== null) {
            return (typeof (value) === 'object' && !isset(value.jquery) && isset(value.length));
        } else {
            return false;
        }
    },
    /**
     * @param {string} text
     * @returns {String}
     */
    "normalize": function (text) {
        var accentMap = {
            "à": "a", "ã": "a", "â": "a", "ä": "a", "ª": "a",
            "é": "e", "è": "e", "ê": "e", "ë": "e", "&": "e",
            "í": "i", "ì": "i", "î": "i", "ï": "i",
            "ó": "o", "ò": "o", "õ": "o", "ô": "o", "ö": "o", "º": "o",
            "ú": "u", "ù": "u", "û": "u", "ü": "u",
            "ç": "c"
        };
        var normalizedText = "";
        text = text.toLowerCase();
        for (var i = 0; i < text.length; i++) {
            var character = text.charAt(i);
            normalizedText += accentMap[ character ] || character;
        }
        return normalizedText;
    },
    /**
     * @param {string} text
     * @returns {string}
     */
    "accentStrip": function (text) {
        return text.replace(/[ÀÁÂÃÄÅ]/g, 'A').replace(/[àáâãäå]/g, 'a')
                .replace(/[ÈÉÊË]/g, 'E').replace(/[èéêë]/g, 'e')
                .replace(/[ÌÍÎÏ]/g, 'I').replace(/[ìíîï]/g, 'i')
                .replace(/[ÒÓÔÕÖ]/g, 'O').replace(/[òóôõö]/g, 'o')
                .replace(/[ÙÚÛÜ]/g, 'U').replace(/[ùúûü]/g, 'u')
                .replace(/[Ç]/g, 'C').replace(/[ç]/g, 'c')
                .replace(/[Ñ]/g, 'N').replace(/[ñ]/g, 'n');
    },
    /**
     * Retorna as informações de um input sem a máscara.
     * Remove por padrão "-"(hífen),"."(ponto),"/"(barra),":"(dois pontos),"_"(underline) e espaços.
     *
     * @param {object jQuery} input
     * @param {Array} arrAddCaracteres Array com os caracteres que são para remover do valor também.
     * @return {String} o valor sem os caracteres de mascara e/ou os caracteres no array enviado por parâmetro.
     */
    "getValUnmasked": function (input, arrAddCaracteres) {
        var sValue = input.val();
        sValue = (isset(sValue) && sValue !== null) ? sValue.toString().replace(/[\(\)\-\.\/\:\_\s]/g, "") : '';
        if (arrAddCaracteres) {
            var i;
            var j;
            for (j = 0; j < arrAddCaracteres.length; j++) {
                i = 0;
                while (i < sValue.length) {
                    sValue = sValue.toString().replace(arrAddCaracteres[j], "");
                    i++;
                }
            }
        }
        return $.trim(sValue);
    },
    /**
     * Transforma em JSON o element.serialize()
     * 
     * @param {object jQuery} element
     * @returns {object}
     */
    "parseJSON": function (element) {
        try {

//        $search  = array('\\', "\n", "\t", "\r", "\b", "\f", '"', '/');
//        $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"', '\\/');

            var serializedData = element.serialize()
                    .replace(/%22/gi, '\\\"') //aspa dupla
                    .replace(/%0A/gi, "\\n")  //quebra de linha
                    .replace(/%5C/gi, "\\\\") //contra barra
                    .replace(/\t/gi, "    "); //tabulação

            var jsonStr = serializedData.replace(/=&/g, '" : "",    "');
            jsonStr = jsonStr.replace(/=/g, '" : "');
            jsonStr = jsonStr.replace(/&/g, '",    "');
            jsonStr = decodeURIComponent(jsonStr.replace(/\+/g, " "));
            if (jsonStr !== "") {
                jsonStr = '{"' + jsonStr + '"}';
            }
            jsonStr = jsonStr.replace(/\t/g, "    ");
            return $.parseJSON(jsonStr);
        } catch (e) {
            Core.exceptionHandler(e);
        }
    }
};



